package cn.wolfcode.luowowo.service.impl;

import cn.wolfcode.luowowo.cache.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.cache.util.RedisKeys;
import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.exception.LogicException;
import cn.wolfcode.luowowo.query.SearchQueryObject;
import cn.wolfcode.luowowo.repository.UserInfoRepository;
import cn.wolfcode.luowowo.service.IUserInfoService;
import cn.wolfcode.luowowo.util.AssertUtil;
import cn.wolfcode.luowowo.util.DBHelper;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
//@Transactional 目前单体mongodb不支持事务
public class UserInfoServiceImpl implements IUserInfoService {
    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private IUserInfoRedisService redisService;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public UserInfo get(String id) {
        return userInfoRepository.findById(id).get();
    }

    @Override
    public boolean checkPhone(String phone) {
        UserInfo user = userInfoRepository.findByPhone(phone);
        return user != null;
    }



    @Override
    public void insert(UserInfo userInfo) {
        userInfo.setId(null);
        userInfoRepository.insert(userInfo);
    }

    @Override
    public void update(UserInfo userInfo) {
//        Query query = new Query();
//        DBHelper.update(mongoTemplate, query, userInfo, "favors");
        userInfoRepository.save(userInfo);
    }

    @Override
    public String sendVerifyCode(String phone, String smsUrl, String smsSign, String smsAppkey) {
        //生成验证码
        String code = UUID.randomUUID().toString().replaceAll("-", "")
                .substring(0, 4);

        //发送短信
        StringBuilder sb = new StringBuilder(100);
        sb.append("您好，注册验证码是：").append(code).append("，请在")
                .append(5).append("分钟之内使用");

//        String url = "https://way.jd.com/chonry/smsnotice?sign=【螺窝窝】" +
//                "&mobile=" + phone + "&content=" + sb.toString() + "&appkey=e328c3f0c466296ec44699afd1942ad3";

        RestTemplate restTemplate = new RestTemplate();

//        Map map = restTemplate.getForObject(url, Map.class, phone, sb.toString(), "e328c3f0c466296ec44699afd1942ad3");

        String ret = restTemplate.getForObject(smsUrl, String.class, smsSign, phone, sb.toString(), smsAppkey);

        System.out.println(sb.toString());
        System.out.println(ret);

        //缓存验证码：redis 有效时间5分钟
        redisService.setVerifyCode(phone, code);
        return code;
    }

    @Override
    public String setLimit(String phone) {
        return redisService.setLimit(phone);
    }

    @Override
    public void decrLimit(String phone) {
        redisService.decrLimit(phone);
    }

    @Override
    public void regist(UserInfo userInfo, String rpassword, String verifyCode) {
        //判断参数是否为空
        AssertUtil.hasLength(userInfo.getPhone(), "手机号码不能为空");
        AssertUtil.hasLength(userInfo.getNickname(), "昵称不能为空");
        AssertUtil.hasLength(userInfo.getPassword(), "密码不能为空");
        AssertUtil.hasLength(rpassword, "确认密码不能为空");
        AssertUtil.hasLength(verifyCode, "验证码不能为空");

        //判断2次密码是否一致
        AssertUtil.isEquals(userInfo.getPassword(), rpassword, "2次输入密码不一致");

        //判断手机号码格式 TODO 正则

        //判断手机号码是否唯一
        if (this.checkPhone(userInfo.getPhone())) {
            throw new LogicException("手机号码已经被注册了");
        }

        //判断验证码是否一致
        String vc = redisService.get(RedisKeys.VERIFY_CODE.join(userInfo.getPhone()));
        if (verifyCode == null || !vc.equals(verifyCode)) {
            throw new LogicException("验证码错误");
        }

        //注册
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setPhone(userInfo.getPhone());
        userInfo1.setNickname(userInfo.getNickname());
        userInfo1.setPassword(userInfo.getPassword());
        userInfo1.setEmail("");
        userInfo1.setCity("");
        userInfo1.setInfo("");
        userInfo1.setLevel(1);
        userInfo1.setHeadImgUrl("/images/blackman.jpg");

        this.insert(userInfo1);
    }

    @Override
    public UserInfo login(String username, String password) {
//        UserInfo user = userInfoRepository.findByPhoneAndPassword(username, password);
        UserInfo user = userInfoRepository.findByPhone(username);
        if (user == null || !password.equals(user.getPassword())) {
            throw new LogicException("登录错误");
        }

        return user;
    }

    @Override
    public String svc(String phone) {
        //生成验证码
        String code = UUID.randomUUID().toString().replaceAll("-", "")
                .substring(0, 4);

        //发送短信
        StringBuilder sb = new StringBuilder(100);
        sb.append("您好，注册验证码是：").append(code).append("，请在")
                .append(5).append("分钟之内使用");

        String url = "https://way.jd.com/BABO/sms?mobile=" + phone +
                "&msg=" + sb.toString() + "&appkey=81f14423cf99aadcd33dc1dcbe0d922f";

        RestTemplate restTemplate = new RestTemplate();

//        Map map = restTemplate.getForObject(url, Map.class, phone, sb.toString(), "e328c3f0c466296ec44699afd1942ad3");

        String ret = restTemplate.getForObject(url, String.class);

        System.out.println(sb.toString());
        System.out.println(ret);

        //缓存验证码：redis 有效时间5分钟
        redisService.setVerifyCode(phone, code);
        return code;
    }

    @Override
    public List<UserInfo> listByKeyword(SearchQueryObject qo) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.andOperator(
                Criteria.where("info").regex(".*" + qo.getKeyword() + ".*"),
                Criteria.where("city").regex(".*" + qo.getKeyword() + ".*")
        );
        query.addCriteria(criteria);
        List<UserInfo> users = mongoTemplate.find(query, UserInfo.class, "userInfo");
        return users;
    }

    @Override
    public Page<UserInfo> queryByKeyword(SearchQueryObject qo) {
        Query query = new Query();
        Criteria criteria = new Criteria();
        criteria.andOperator(
                Criteria.where("info").regex(".*" + qo.getKeyword() + ".*"),
                Criteria.where("city").regex(".*" + qo.getKeyword() + ".*")
        );
        query.addCriteria(criteria);
        PageRequest pageable = PageRequest.of(qo.getCurrentPage() - 1, 5
                , Sort.Direction.ASC, "_id");
        return DBHelper.query(mongoTemplate, UserInfo.class, query, pageable);
    }

    @Override
    public List<UserInfo> listAll() {
        return userInfoRepository.findAll();
    }

    @Override
    public List<UserInfo> insertUid(String userId, String id) {
        String uidKey = RedisKeys.USER_UIDS.join(userId);
        String uidStr = redisTemplate.opsForValue().get(uidKey);
        List<String> uids = JSON.parseArray(uidStr, String.class);
        List<UserInfo> users = new ArrayList<>();
        if (!id.equals(userId)) {
            if (!(uids.contains(id))) {
                redisService.incrTTV(userId);
                redisService.incrTDV(userId);
                uids.add(id);
                redisTemplate.opsForValue().set(uidKey, JSON.toJSONString(uids));
            }
        }
        for (String uid : uids) {
            UserInfo u = userInfoRepository.findById(uid).get();
            users.add(u);
        }
        if (users.size() >= 8) {
            users = users.subList(0, 8);
        }
        return users;
    }

    @Override
    public List<UserInfo> getUsers(String uid) {
        UserInfo userInfo = userInfoRepository.findById(uid).get();
        List<String> uids = userInfo.getUids();
        List<UserInfo> users = new ArrayList<>();
        for (String id : uids) {
            UserInfo user = userInfoRepository.findById(id).get();
            users.add(user);
        }
        return users;
    }
}
